package com.ruiyian.project.predict.service.impl;

import com.baomidou.dynamic.datasource.annotation.DS;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.ruiyian.common.utils.DateUtils;
import com.ruiyian.common.utils.file.FileUtils;
import com.ruiyian.project.predict.domain.RecordMsg;
import com.ruiyian.project.predict.domain.SimuMsg;
import com.ruiyian.project.predict.mapper.PredictMapper;
import com.ruiyian.project.predict.service.PredictService;
import lombok.extern.slf4j.Slf4j;
import org.apache.ibatis.session.ExecutorType;
import org.apache.ibatis.session.SqlSession;
import org.mybatis.spring.SqlSessionTemplate;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;

import java.io.File;
import java.util.*;
import java.util.stream.Collectors;

/**
 * @author chong
 * @email 673426164@qq.com
 * @create 2021/12/14
 * Desc: 道路预测
 */
@Slf4j
@Service
public class PredictServiceImpl implements PredictService {
    @Value("${simulation.writeDataPath}")
    private String writeDataPath;
    @Value("${simulation.writeMsgPath}")
    private String writeMsgPath;
    @Autowired
    private PredictMapper predictMapper;
    @Autowired
    SqlSessionTemplate sqlSessionTemplate;
    /**
     * 读取数据
     * @return
     */
    @Override
    public  List<Map<String, Object>> readDataFlowPre(String path) {
        List<Map<String, Object>> dataList = Lists.newArrayList();
        List<Map<String, Object>> maps = FileUtils.readDatFileContent(path);
        if(null!= maps && maps.size()>0){
            Map<String, List<Map<String, Object>>> mapList = maps.stream().collect(Collectors.groupingBy(f -> f.get("var1").toString()));
            for(Map.Entry<String, List<Map<String, Object>>> entry: mapList.entrySet()){
                Map<String, Object> data = Maps.newHashMap();
                List<String> xTime = new ArrayList<>();
                List<Object> actualIn = new ArrayList<>();
                List<Object> actualOut = new ArrayList<>();
                List<Object> predictIn = new ArrayList<>();
                List<Object> predictOut = new ArrayList<>();
                data.put("name",entry.getKey());
                List<Map<String, Object>> coll = new ArrayList<>();
                Map<String, List<Map<String, Object>>> timeMap = entry.getValue().stream().collect(Collectors.groupingBy(p -> p.get("var0").toString(),TreeMap::new,Collectors.toList()));
                for(Map.Entry<String, List<Map<String, Object>>> en: timeMap.entrySet()) {
                    Map<String, Object> nData = new HashMap<>();
                    nData.put("var0",en.getKey());
                    nData.put("var3",en.getValue().stream().mapToLong(f->Long.parseLong(f.get("var3").toString())).sum());
                    nData.put("var4",en.getValue().stream().mapToLong(f->Long.parseLong(f.get("var4").toString())).sum());
                    nData.put("var5",en.getValue().stream().mapToLong(f->Long.parseLong(f.get("var5").toString())).sum());
                    nData.put("var6",en.getValue().stream().mapToLong(f->Long.parseLong(f.get("var6").toString())).sum());
                    coll.add(nData);
                }
                for(Map<String, Object> m: coll){
                    xTime.add(m.get("var0").toString());
                    actualIn.add(m.get("var3"));
                    actualOut.add(m.get("var4"));
                    predictIn.add(m.get("var5"));
                    predictOut.add(m.get("var6"));
                }
                // 流量预测
                List<Map<String, Object>> flowPre = Lists.newArrayList();
                String[] split ={"实际入口","实际出口","预测入口","预测出口"};
                for(int i=0;i<split.length;i++){
                    Map<String,Object> obj = Maps.newHashMap();
                    obj.put("name",split[i]);
                    switch (i){
                        case 0: obj.put("data",actualIn);
                            break;
                        case 1: obj.put("data",actualOut);
                            break;
                        case 2: obj.put("data",predictIn);
                            break;
                        case 3: obj.put("data",predictOut);
                            break;
                    }
                    obj.put("type","line");
                    obj.put("symbol","circle");
                    flowPre.add(obj);
                }
                data.put("series",flowPre);
                data.put("xTime",xTime);
                dataList.add(data);
            }
        }
        return dataList;
    }

    /**
     * 读取拥堵点数据
     * @return
     */
    @Override
    public List<Map<String, Object>> readDataCongestionPoint(String path) {
        List<Map<String, Object>> maps = FileUtils.readDatFileContent(path);
        return maps;
    }
    /**
     * 读取道路措施数据
     * @return
     */
    @Override
    public List<Map<String, Object>> readDataAction(String path) {
        List<Map<String, Object>> maps = FileUtils.readDatFileContent(path);
        return maps;
    }

    /**
     * 创建
     * ENTRY.dat
     */
    @Override
    public void createData(List<Map<String,String>> list) {
        String dateTime = DateUtils.parseDateToStr("yyyyMMddHHmm", new Date());
        System.out.println(dateTime);
        List<Map<String,String>> lists = new ArrayList<>();
        Map<String,String> map = Maps.newHashMap();
        map.put("var0","vehicleType");
        map.put("var1","vehicleId");
        map.put("var2","enTime");
        map.put("var3","enStationId");
        map.put("var4","enTollStationName");
        map.put("var5","enTollLaneId");
        list.add(map);
        Map<String,String> map1 = Maps.newHashMap();
        map.put("var0","1");
        map.put("var1","默A00000_9");
        map.put("var2","2020-05-22 10:18:47");
        map.put("var3","G0422440020010");
        map.put("var4","仑头");
        map.put("var5","xxx");
        list.add(map1);
        File file= new File(writeDataPath);
        FileUtils.circleMethod(file,"ENTRY.dat",lists);
    }
    /**
     * 保存simu文件
     * @param path
     */
    @Override
    public void saveSimuMsg(String path) {
       Map recordMap = FileUtils.readFileContent(path);
       if(null != recordMap && recordMap.size()>0){
           try {
               File file = new File(path);
               recordMap.put("FILE_NAME",file.getName());
               predictMapper.save(recordMap);
               file.delete(); //处理完删除文件
           } catch (Exception e) {
               log.error("保存仿真消息失败"+e.getMessage());
           }
       }
    }
    /**
     * 保存仿真录像视频
     */
    @Override
    public void saveRecordMsg(String path) {
        Map recordMap = FileUtils.readFileContent(path);
        if(null != recordMap && recordMap.size()>0){
            try {
                File file = new File(path);
                recordMap.put("FILE_NAME",file.getName());
                predictMapper.saveRecordMsg(recordMap);
                file.delete(); //处理完删除文件
            } catch (Exception e) {
                log.error("保存仿真视频消息失败"+e.getMessage());
            }
        }
    }
    /**
     * 获取最新
     * @return
     */
    @Override
    public SimuMsg selectNewData() {
        return predictMapper.selectNewData();
    }

    /**
     * 根据抢号获取最新仿真视频
     * @param code
     * @return
     */
    @Override
    public RecordMsg selectNewRecordDataByCode(String code) {
        return predictMapper.selectNewRecordDataByCode(code);
    }

    /**
     * 抢号,实例id
     * @param code
     * @param runId
     * @return
     */
    @Override
    public RecordMsg selectNewRecordDataByCodeAndRunId(String code, Integer runId) {
        return predictMapper.selectNewRecordDataByCodeAndRunId(code, String.valueOf(runId));
    }

    /**
     * 入口数据
     * @return
     */
    @DS("salve")
    @Override
    public List<Map<String, String>> queryEntryData(String startTime, String endTime) {
        List<Map<String, String>> list =  predictMapper.queryEntryData(startTime, endTime);
        if(null == list){
            list = new ArrayList<>();
        }
        Map<String,String> map = Maps.newHashMap();
        map.put("var0","passId");
        map.put("var1","vehicleType");
        map.put("var2","vehicleId");
        map.put("var3","enTime");
        map.put("var4","enStationId");
        map.put("var5","enTollStationName");
        map.put("var6","enTollLaneId");
        list.add(0,map);
        return list;
    }

    /**
     * 出口
     * @param startTime
     * @param endTime
     * @return
     */
    @DS("salve")
    @Override
    public List<Map<String, String>> queryExitData(String startTime, String endTime) {
        List<Map<String, String>> list =  predictMapper.queryExitData(startTime, endTime);
        if(null == list){
            list = new ArrayList<>();
        }
        Map<String,String> map = Maps.newHashMap();
        map.put("var0","passId");
        map.put("var1","vehicleType");
        map.put("var2","vehicleId");
        map.put("var3","enTime");
        map.put("var4","enStationId");
        map.put("var5","enTollStationName");
        map.put("var6","exTime");
        map.put("var7","exStationId");
        map.put("var8","exTollStationName");
        map.put("var9","enTollLaneId");
        map.put("var10","exTollLaneId");
        list.add(0,map);
        return list;
    }

    /**
     * 门架
     * @param startTime
     * @param endTime
     * @return
     */
    @DS("salve")
    @Override
    public List<Map<String, String>> queryDoorFrameData(String startTime, String endTime) {
        List<Map<String, String>> list = predictMapper.queryDoorFrameData(startTime, endTime);
        if(null == list){
            list = new ArrayList<>();
        }
        Map<String,String> map = Maps.newHashMap();
        map.put("var0","passId");
        map.put("var1","vehicleType");
        map.put("var2","vehicleId");
        map.put("var3","transTime");
        map.put("var4","gantryId");
        map.put("var5","direction");
        list.add(0,map);
        return list;
    }
    /**
     * 批量添加入口数据
     * @param list
     */
    @Override
    public void batchAddEntry(List<Map<String, String>> list) {
        SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);//跟上述sql区别
        PredictMapper entryMapper = sqlSession.getMapper(PredictMapper.class);
        for(Map<String, String> map: list){
            entryMapper.batchEntrySave(map);
        }
        sqlSession.commit();
    }
    /**
     * 批量添加出口数据
     * @param list
     */
    @Override
    public void batchExitSave(List<Map<String, String>> list) {
        SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);//跟上述sql区别
        PredictMapper entryMapper = sqlSession.getMapper(PredictMapper.class);
        for(Map<String, String> map: list){
            entryMapper.batchExitSave(map);
        }
        sqlSession.commit();
    }
    /**
     * 批量添加门架数据
     * @param list
     */
    @Override
    public void batchDoorSave(List<Map<String, String>> list) {
        SqlSession sqlSession = sqlSessionTemplate.getSqlSessionFactory().openSession(ExecutorType.BATCH, false);//跟上述sql区别
        PredictMapper entryMapper = sqlSession.getMapper(PredictMapper.class);
        for(Map<String, String> map: list){
            entryMapper.batchDoorSave(map);
        }
        sqlSession.commit();
    }
}
